#ifndef __M_HOST_H__
#define __M_HOST_H__
// 引入消息队列核心组件头文件
#include "mq_exchange.hpp" // 交换机管理
#include "mq_queue.hpp"    // 队列管理
#include "mq_binding.hpp"  // 绑定关系管理
#include "mq_message.hpp"  // 消息存储管理

namespace zdfmq
{

    /**
     * 虚拟主机类：消息队列系统的核心容器
     * 功能：
     *  1. 聚合交换机、队列、绑定、消息的管理逻辑
     *  2. 实现各组件之间的联动（如删除交换机时同步删除绑定）
     *  3. 封装虚拟主机的完整生命周期管理
     */
    class VirtualHost
    {
    public:
        // 智能指针类型别名，统一使用 shared_ptr 管理对象
        using ptr = std::shared_ptr<VirtualHost>;

        /**
         * 构造函数：初始化虚拟主机的核心组件
         * @param hname       虚拟主机名称
         * @param basedir     消息存储的基础目录（用于持久化消息）
         * @param dbfile      元数据数据库文件路径（用于存储交换机、队列、绑定信息）
         */
        VirtualHost(const std::string &hname, const std::string &basedir, const std::string &dbfile)
            : _host_name(hname),
              // 初始化各管理器：使用同一数据库文件保证元数据一致性
              _emp(std::make_shared<ExchangeManager>(dbfile)),
              _mqmp(std::make_shared<MsgQueueManager>(dbfile)),
              _bmp(std::make_shared<BindingManager>(dbfile)),
              _mmp(std::make_shared<MessageManager>(basedir))
        {

            // 恢复队列消息：从数据库加载所有队列，并初始化消息存储句柄
            QueueMap qm = _mqmp->allQueues();
            for (auto &q : qm)
            {
                _mmp->initQueueMessage(q.first); // 为每个队列初始化消息存储
            }
        }

        // ====================== 交换机管理 ======================
        /**
         * 声明（创建）交换机
         * @param name        交换机名称
         * @param type        交换机类型（如 DIRECT、TOPIC 等）
         * @param durable     是否持久化
         * @param auto_delete 是否自动删除
         * @param args        额外参数（Protobuf Map 类型）
         */
        bool declareExchange(const std::string &name,
                             ExchangeType type, bool durable, bool auto_delete,
                             const google::protobuf::Map<std::string, std::string> &args)
        {
            return _emp->declareExchange(name, type, durable, auto_delete, args);
        }

        /**
         * 删除交换机：联动删除相关绑定信息
         * @param name  交换机名称
         */
        void deleteExchange(const std::string &name)
        {
            _bmp->removeExchangeBindings(name); // 先删除绑定
            _emp->deleteExchange(name);         // 再删除交换机
        }

        /**
         * 检查交换机是否存在
         * @param name  交换机名称
         */
        bool existsExchange(const std::string &name)
        {
            return _emp->exists(name);
        }

        /**
         * 查询交换机
         * @param ename 交换机名称
         */
        Exchange::ptr selectExchange(const std::string &ename)
        {
            return _emp->selectExchange(ename);
        }

        // ====================== 队列管理 ======================
        /**
         * 声明（创建）队列：联动初始化消息存储
         * @param qname       队列名称
         * @param qdurable    是否持久化
         * @param qexclusive  是否独占
         * @param qauto_delete 是否自动删除
         * @param qargs       额外参数（Protobuf Map 类型）
         */
        bool declareQueue(const std::string &qname,
                          bool qdurable,
                          bool qexclusive,
                          bool qauto_delete,
                          const google::protobuf::Map<std::string, std::string> &qargs)
        {
            _mmp->initQueueMessage(qname); // 初始化消息存储（即使队列创建失败，也需保证幂等性）
            return _mqmp->declareQueue(qname, qdurable, qexclusive, qauto_delete, qargs);
        }

        /**
         * 删除队列：联动清理消息存储和绑定信息
         * @param name  队列名称
         */
        void deleteQueue(const std::string &name)
        {
            _mmp->destroyQueueMessage(name);    // 清理消息存储
            _bmp->removeMsgQueueBindings(name); // 清理绑定
            _mqmp->deleteQueue(name);           // 清理队列元数据
        }

        /**
         * 检查队列是否存在
         * @param name  队列名称
         */
        bool existsQueue(const std::string &name)
        {
            return _mqmp->exists(name);
        }

        /**
         * 获取所有队列的元数据
         */
        QueueMap allQueues()
        {
            return _mqmp->allQueues();
        }

        // ====================== 绑定管理 ======================
        /**
         * 绑定交换机与队列：需校验交换机和队列是否存在
         * @param ename  交换机名称
         * @param qname  队列名称
         * @param key    绑定键（用于消息路由）
         */
        bool bind(const std::string &ename, const std::string &qname, const std::string &key)
        {
            // 校验交换机存在性
            Exchange::ptr ep = _emp->selectExchange(ename);
            if (!ep)
            {
                DLOG("绑定失败：交换机 %s 不存在", ename.c_str());
                return false;
            }

            // 校验队列存在性
            MsgQueue::ptr mqp = _mqmp->selectQueue(qname);
            if (!mqp)
            {
                DLOG("绑定失败：队列 %s 不存在", qname.c_str());
                return false;
            }

            // 持久化策略：仅当交换机和队列都持久化时，绑定才持久化
            return _bmp->bind(ename, qname, key, ep->durable && mqp->durable);
        }

        /**
         * 解除绑定
         * @param ename  交换机名称
         * @param qname  队列名称
         */
        void unBind(const std::string &ename, const std::string &qname)
        {
            _bmp->unbind(ename, qname);
        }

        /**
         * 获取指定交换机的所有绑定
         * @param ename  交换机名称
         */
        MsgQueueBindingMap exchangeBindings(const std::string &ename)
        {
            return _bmp->getExchangeBindings(ename);
        }

        /**
         * 检查绑定是否存在
         * @param ename  交换机名称
         * @param qname  队列名称
         */
        bool existsBinding(const std::string &ename, const std::string &qname)
        {
            return _bmp->exists(ename, qname);
        }

        // ====================== 消息管理 ======================
        /**
         * 发布消息到队列
         * @param qname  队列名称
         * @param bp     消息属性（Protobuf 结构）
         * @param body   消息体
         */
        bool basicPublish(const std::string &qname, BasicProperties *bp, const std::string &body)
        {
            MsgQueue::ptr mqp = _mqmp->selectQueue(qname);
            if (!mqp)
            {
                DLOG("发布失败：队列 %s 不存在", qname.c_str());
                return false;
            }
            // 根据队列持久化策略决定消息是否持久化
            return _mmp->insert(qname, bp, body, mqp->durable);
        }

        /**
         * 消费队列中的第一条消息
         * @param qname  队列名称
         */
        MessagePtr basicConsume(const std::string &qname)
        {
            return _mmp->front(qname);
        }

        /**
         * 确认消息消费完成（从队列中移除）
         * @param qname  队列名称
         * @param msgid  消息ID
         */
        void basicAck(const std::string &qname, const std::string &msgid)
        {
            _mmp->ack(qname, msgid);
        }

        // ====================== 清理操作 ======================
        /**
         * 清理所有资源：交换机、队列、绑定、消息
         */
        void clear()
        {
            _emp->clear();  // 清理交换机
            _mqmp->clear(); // 清理队列
            _bmp->clear();  // 清理绑定
            _mmp->clear();  // 清理消息
        }

    private:
        // 虚拟主机名称（用于标识和区分不同虚拟主机）
        std::string _host_name;

        // 各组件管理器：
        ExchangeManager::ptr _emp;  // 交换机管理器
        MsgQueueManager::ptr _mqmp; // 队列管理器
        BindingManager::ptr _bmp;   // 绑定管理器
        MessageManager::ptr _mmp;   // 消息管理器
    };

} // namespace zdfmq

#endif // __M_HOST_H__